/**
 * Это класс виджета поля выпадающего списка.
 * Copyright 2012, Alexander Dashkovsky
 * License: http://www.opensource.org/licenses/mit-license.php
 * @lends widget.ComboboxStd
 */
widget.ComboboxStd = widget.Control.extend({

    /** @const */
    WIDGET_CLASS : 'wg_comboboxstd',
    /**
 *  МОДЕРНИЗИРОВАНЫЙ ВИДЖЕТ! БЕЗ  ПОМЕЩЕНИЯ В DIV И TABLE
 */
    /**
	 * Конструктор класса
	 * @augments widget.Control
	 * @class Класс виджета стандартного HTML поля выпадающего списка.
	 * Элементами списка могут быть только текстовые строки.
	 * 
	 * <p><b>CSS класс для DOM элемента - <code>wg_comboboxstd</code></b></p>
	 * 
	 * <p><b>Параметры объекта конфигурации:</b></p>
	 * {String} <b>id</b> - Идентификатор компонента ComboBox.</br>
	 * {String} <b>cls</b> - Имя класса css (или нескольких классов через пробел)
	 * которые будут добавлены к ComboBox.</br>
	 * {Object} <b>label</b> - Элемент метки поля.
	 * <div class="shift1">{String} <b>label.text</b> - Текст метки</div>
	 * <div class="shift1">{String} <b>label.cls</b> - Имя класса css, которое 
	 * будет применено к тексту метки</div>
	 * <div class="shift1">{String} <b>label.align</b> - Расположение текста метки 
	 * по отношению к полю. Возможные значения:</div>
	 * <div class="shift2">'<b>'left'</b>' - Текст метки прижат к левому краю выделенной области</div>
	 * <div class="shift2">'<b>'top'</b>' - Текст метки сверху над полем</div>
	 * <div class="shift2">'<b>'right'</b>' - Текст метки прижат к правому краю выделенной области</div>
	 * <div class="shift1">Если атрибут label.align не задан, текст метки будет
	 * прижат к левому краю выделенной области (когда label.width задан).</div> 
	 * <div class="shift1">{Int} <b>label.width</b> - Ширина области, отведенной
	 * под текст метки. Если не задано, label и field следуют друг за другом.</div>
	 * {Object} <b>input</b> - Элемент поля выбора.
	 * <div class="shift1">{String} <b>input.cls</b> - Имя класса css, которое 
	 * будет применено к полю выбора.</div>
	 * <div class="shift1">{Int} <b>input.width</b> - Ширина элемента поля выбора.</div>
	 * {Object[]} <b>items</b> - Массив объектов выбора.
	 * <div class="shift1">{String} <b>items[i].value</b> - Уникальное значение объекта выбора.</div>
	 * <div class="shift1">{String} <b>items[i].text</b> - Текст объекта выбора.</div>
	 * {String} <b>value</b> - Значение элемента из списка ComboBox, которое 
	 * будет показано при прорисовке компонента.</br>
	 * {ElementDOM} <b>renderTo</b> - Элемент DOM, в который будет прорисована кнопка.</br>
	 * {Object[]} <b>listeners</b> - Массив слушателей событий.</br>
	 * 
	 * <p><b>События:</b></p>
	 * <div><b>afterrender</b> - Вызывается сразу после прорисовки поля.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент поля.</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент поля.</div>
	 * <div><b>click</b> - Вызывается при клике на область компонента.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент поля</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент поля</div>
	 * <div><b>change</b> - Вызывается при выборе из списка нового эламента.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>record</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент поля</div>
	 * <div class="shift2"><b>record</b> - запись выбранного элемента из списка.</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент поля.</div>
	 * <div><b>hide</b> - Вызывается когда кнопка была спрятана.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент кнопки</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент кнопки</div>
	 * <div><b>show</b> - Вызывается когда кнопка была показана.</div>
	 * <div class="shift1">callbackFunction(<b>component</b>, <b>domElement</b>), где:</div>
	 * <div class="shift2"><b>component</b> - компонент кнопки</div>
	 * <div class="shift2"><b>domElement</b> - DOM элемент кнопки</div>
	 * 
	 * <p><b>Пример:</b></p>
	 * <pre class="code">
	 * var cb1 = new widget.ComboboxStd({
	 * 	id : 'cb1',
	 * 	cls : 'cb',
	 * 	label : {
	 * 		text : 'Цвет:',
	 * 		cls : 'label',
	 * 		align : 'left',
	 * 		width : 70
	 * 	},
	 * 	input : {
	 * 		cls : 'select',
	 * 		width : 180
	 * 	},
	 * 	value : '3',
	 * 	items : [
	 * 		{ value:'0', text:'--Выберите цвет--'},
	 * 		{ value:'1', text:'Синий'},
	 * 		{ value:'2', text:'Красный'},
	 * 		{ value:'3', text:'Зелёный'},
	 * 		{ value:'4', text:'Желтый'}
	 * 	],
	 * 	renderTo : $('#controls'),
	 * 	listeners : {
	 * 		change : function(field, record, elementDom){
	 * 			console.log('Selected value='+record.value+', text='+record.text);
	 * 		}
	 * 	}
	 * });
	 * </pre>
	 * 
	 * @constructs
	 * @param {object} config Конфигурационный объект компонента.
	 */
    constructor : function(config) {
        this.config = config || {} ;
        this.base(this.config.id, this.WIDGET_CLASS,
            this.config.label, this.config.value);
        if (this.config.renderTo) {
            this.render(this.config.renderTo);
        }
    },
	
    /**
	 * Выполняется отрисовка поля.
	 * @public 
	 * @function
	 * @memberOf widget.ComboboxStd#
	 * @param (elementDOM) renderTo Элемент DOM, внутри которого будет создано поле.
	 * Если этот параметр не задавать, а поле уже ранее прорисовывалось, то оно 
	 * будет перерисоваться в тот же контейнер. Если в контейнере существуют и 
	 * другие виджеты, render() без параметра прорисует этот виджет после всех 
	 * остальных.
	 * @return none
	 */
    render : function(renderTo) {
        var me = this;
        if (this.element) {
            this.element.remove();
        }
		
        if (renderTo) {
            this.renderContainer = renderTo;
        } else {
            renderTo = this.renderContainer;
        }
		
        var selectTpl = '<select';
        if (this.config.name) {
            selectTpl += ' name="'+this.config.name+'"';
        }
        selectTpl += '>';
        if (this.config.items) {
            for (var i=0; i<this.config.items.length; i++) {
                var option = this.config.items[i];
                if (typeof this.selectedItem == 'undefined')
                    this.selectedItem = option;
                selectTpl += '<option value="'+option.value+'"';
                if (this.getValue() == option.value) {
                    selectTpl += ' selected';
                    this.selectedItem = option; 
                }
                selectTpl += '>'+option.text+'</option>'
            }
			
        }
        selectTpl += '</select>';

        var tpl = selectTpl;
        if (this.element) {
            this.element.remove();
        }
        this.element = $(tpl);
        if (this.config.cls) {
            this.applyClassToElement(this.config.cls, this.element)
        }
		
        this.labelEl = $(this.element).find("label");
        if (this.config.label && this.config.label.cls) {
            $(this.labelEl).addClass(this.config.label.cls);
        }
        if (this.config.label && this.config.label.width) {
            this.labelEl.parent().width(this.config.label.width);
        }
		
        this.fieldEl = $(this.element).find("select");
        if (this.config.input && this.config.input.width) {
            this.fieldEl.width(this.config.input.width);
        }
        if (this.config.input && this.config.input.cls) {
            $(this.fieldEl).addClass(this.config.input.cls);
        }

        if (renderTo) {
            $(this.element).appendTo(renderTo);
            this.visible = true;
            $(this.element).click(function(event) {
                me.onClick();
                (window.event) ? event.cancelBubble = true : event.stopPropagation();
            });
            $(this.fieldEl).change(function() {
                var val = $(this).find(":selected").val();
                for (var i=0; i<me.config.items.length; i++) {
                    var option = me.config.items[i];
                    if (val == option.value) {
                        me.selectedItem = option; 
                    }
                }
                me.setValue(val);
                me.selectedText = $(this).find(":selected").text();
                $(this).parent().find('span').text(me.selectedText);
                me.onChange();
            });
            this.onAfterRender();
        }
    },
	
    /**
	 * Функция отрабатывает сразу после прорисовки конпонента. 
	 * @private 
	 * @function
	 */
    onAfterRender : function() {
        if (this.config.listeners && this.config.listeners.afterrender) {
            this.config.listeners.afterrender(this, this.element);
        }
    },
	
    /**
	 * Функция отрабатывает сразу после клика мышки на компоненте. 
	 * @private 
	 * @function
	 */
    onClick : function() {
        if (this.config.listeners && this.config.listeners.click) {
            this.config.listeners.click(this, this.element);
        }
    },
	
    /**
	 * Функция отрабатывает сразу после выбора любого элемента из списка. 
	 * @private 
	 * @function
	 */
    onChange : function() {
        if (this.config.listeners && this.config.listeners.change) {
            this.config.listeners.change(this, this.selectedItem, this.element);
        }
    },
	
    /**
	 * Спрятать поле 
	 * @public 
	 * @function
	 * @memberOf widget.ComboboxStd#
	 */
    hide : function() {
        var oldVisible = this.visible; 
        this.visible = false;
        if (this.visible != oldVisible) {
            this.element.addClass("hidden");
            this.onHide();
        }
    },
	
    /**
	 * Показать поле 
	 * @public 
	 * @function
	 * @memberOf widget.ComboboxStd#
	 */
    show : function() {
        var oldVisible = this.visible; 
        this.visible = true;
        if (this.visible != oldVisible) {
            this.element.removeClass("hidden");
            this.onShow();
        }
    },
	
    /**
	 * Функция отрабатывает после того, как элемент будет спрятан. 
	 * @private 
	 * @function
	 */
    onHide : function() {
        if (this.config.listeners && this.config.listeners.hide) {
            this.config.listeners.hide(this, this.element);
        }
    },
	
    /**
	 * Функция отрабатывает после того, как элемент будет показан. 
	 * @private 
	 * @function
	 */
    onShow : function() {
        if (this.config.listeners && this.config.listeners.show) {
            this.config.listeners.show(this, this.element);
        }
    },
	
    /**
	 * Возвращает элемент DOM, принадлежащий label 
	 * @public 
	 * @function
	 * @memberOf widget.ComboboxStd#
	 */
    getLabelEl : function() {
        return this.labelEl; 
    },
	
    /**
	 * Возвращает элемент DOM, принадлежащий field 
	 * @public 
	 * @function
	 * @memberOf widget.ComboboxStd#
	 */
    getFieldEl : function() {
        return this.fieldEl; 
    },
	
    /**
	 * Возвращает элемент DOM, принадлежащий контейнеру компонента
	 * @public 
	 * @function
	 * @memberOf widget.ComboboxStd#
	 */
    getRenderContainer : function() {
        return this.renderContainer;
    }

});
